/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.biotecan.genome.cytobandviewer.image;

import com.biotecan.genome.cytobandviewer.data.Chromosome;
import com.biotecan.genome.cytobandviewer.data.ChromosomeBuilder;
import com.biotecan.genome.cytobandviewer.data.Chromosomes;
import com.biotecan.genome.cytobandviewer.data.Cytoband;
import com.biotecan.genome.cytobandviewer.data.Mutation;
import com.biotecan.genome.cytobandviewer.data.MutationType;
import com.biotecan.genome.cytobandviewer.shape.CytobandColor;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author SuFeng
 */
public class MultipleCytobandViewer {

    private static final int x0 = 100;
    private static final int y0 = 100;
    private static final int height = 10;
    private static final int margin = 100;
    //image default width and height 2479
    private static final int _width = 20000;

    private static final String DIR = System.getProperty("user.dir");

  
    public BufferedImage drawMutation(String mutationFile[],boolean drawText){
       Chromosomes[] chromArray = new Chromosomes[mutationFile.length];
      // for(int i=0;i<mutationFile.length;i++){
           chromArray[0] = initChromosomes(mutationFile[0]);
           chromArray[1] = initChromosomes(mutationFile[1]);
       //}
       
      

        int scale = (int) (chromArray[0].getMaxLength() / _width);
        int max = (int) (chromArray[0].getMaxLength() / scale);

        //System.out.println(max);
        BufferedImage image = new BufferedImage(max + x0 + margin, (height + margin) * 24 + y0, BufferedImage.TYPE_INT_RGB);

        Logger.getLogger(MultipleCytobandViewer.class.getName()).log(Level.INFO, "image size is [{0}, {1}] ", new Object[]{image.getWidth(), image.getHeight()});

        Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, max + x0 + margin, (height + margin) * 24 + y0);
        g2d.setBackground(Color.WHITE);

        g2d.setStroke(new BasicStroke(1.2f));

        Font font = g2d.getFont();

        //画出染色体名称
        //FontMetrics fontMetrics = g2d.getFontMetrics();
        
        Chromosome[] chromArray1 = new Chromosome[chromArray[1].getList().size()];
        chromArray[1].getList().toArray(chromArray1);
        
        
        
        int i = 1;
        for (Chromosome chr : chromArray[0].getList()) {
            
            Font newFont = new Font("Arial", Font.BOLD, 30);
            g2d.setFont(newFont);
            //draw score line
            g2d.setColor(CytobandColor.color);
            g2d.setStroke(new BasicStroke(2.0f));
            g2d.drawLine((int) (x0 + chr.getStart() / scale), y0 + (i - 1) * (height + margin) - 10, (int) (x0 + chr.getLength() / scale), y0 + (i - 1) * (height + margin) - 10);

            g2d.setStroke(new BasicStroke(2.0f));
            g2d.setColor(CytobandColor.color);
            g2d.drawString(chr.getChrName(), 10, y0 + (i - 1) * (height + margin) + height);

            g2d.setFont(font);

            List<Cytoband> bands = chr.getBands();

            //begin to draw cytoband one by one
            for (Cytoband cytoband : bands) {
                g2d.setColor(CytobandColor.getColor(cytoband.getColor()));
                g2d.drawRect(x0 + (int) (cytoband.getStart() / scale), y0 + (i - 1) * (height + margin), (int) ((cytoband.getEnd() - cytoband.getStart()) / scale), height);
                g2d.fillRect(x0 + (int) (cytoband.getStart() / scale), y0 + (i - 1) * (height + margin), (int) ((cytoband.getEnd() - cytoband.getStart()) / scale), height);

                //是否显示cytoband名称
                if (drawText) {
                    int x = (int) (x0 + ((cytoband.getEnd()) / (scale)) - (cytoband.getEnd() - cytoband.getStart()) / (2 * scale));
                    if (x < cytoband.getEnd() / scale) {
                        x = (int) ((cytoband.getEnd()) / (scale) + 10);
                    }
                    int y = y0 + (i - 1) * (height + margin) + height + margin/2;
                    //System.out.println(x + "\t" + y);

                    g2d.rotate(-Math.PI / 2, x, y);
                    g2d.setColor(Color.BLACK);
                    newFont = new Font("Arial", Font.BOLD, 15);
                    g2d.setFont(newFont);
                    g2d.drawString(cytoband.getBandName(), x, y);
                    g2d.rotate(Math.PI / 2, x, y);
                }

                g2d.setColor(Color.WHITE);
                g2d.setFont(font);
            }//end draw cytoband

            //begin to draw mutations
            Logger.getLogger(MultipleCytobandViewer.class.getName()).log(Level.INFO, "there are {0} mutations found in chromosome  {1} .", new Object[]{chr.getMutations().size(), chr.getChrName()});
            for (Mutation mutation : chr.getMutations()) {
                int start = (int) mutation.getStart() / scale;
                int stop = (int) mutation.getEnd() / scale;

                int width = stop - start <= 1 ? 3 : stop - start;

                if (mutation.getType() == MutationType.SNP) {
                    g2d.setColor(CytobandColor.SNP);
                } else if (mutation.getType() == MutationType.INDEL) {
                    g2d.setColor(CytobandColor.INDEL);
                } else if (mutation.getType() == MutationType.CNV) {
                    g2d.setColor(CytobandColor.CNV);
                }
                g2d.setStroke(new BasicStroke(3.0F));

                g2d.fillRect(x0 + start, y0 + (i - 1) * (height + margin) - 2 * height, width, 10);
            }
            
            
            //draw another sample mutations
             Logger.getLogger(MultipleCytobandViewer.class.getName()).log(Level.INFO, "there are {0} mutations found in chromosome  {1} .", new Object[]{chromArray1[i-1].getMutations().size(), chromArray1[i-1].getChrName()});
            for (Mutation mutation : chromArray1[i-1].getMutations()) {
                int start = (int) mutation.getStart() / scale;
                int stop = (int) mutation.getEnd() / scale;

                int width = stop - start <= 1 ? 3 : stop - start;

                if (mutation.getType() == MutationType.SNP) {
                    g2d.setColor(CytobandColor.SNP);
                } else if (mutation.getType() == MutationType.INDEL) {
                    g2d.setColor(CytobandColor.INDEL);
                } else if (mutation.getType() == MutationType.CNV) {
                    g2d.setColor(CytobandColor.CNV);
                }
                g2d.setStroke(new BasicStroke(3.0F));

                //3*height
                //g2d.fillRect(x0 + start, y0 + (i - 1) * (height + margin) - 3 * height, width, 10*2);
                g2d.fillRect(x0 + start, y0 + (i - 1) * (height + margin) - 4 * height, width, 10);
            }
            
            
            //reset color
            g2d.setColor(Color.WHITE);
            i++;
            //break;
        }

        g2d.dispose();
        return image;
    }
    

    public BufferedImage drawImage(String mutationFile,boolean drawText) {
        Chromosomes chroms = initChromosomes(mutationFile);

        int scale = (int) (chroms.getMaxLength() / _width);
        int max = (int) (chroms.getMaxLength() / scale);

        //System.out.println(max);
        BufferedImage image = new BufferedImage(max + x0 + margin, (height + margin) * 24 + y0, BufferedImage.TYPE_INT_RGB);

        Logger.getLogger(MultipleCytobandViewer.class.getName()).log(Level.INFO, "image size is [{0}, {1}] ", new Object[]{image.getWidth(), image.getHeight()});

        Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, max + x0 + margin, (height + margin) * 24 + y0);
        g2d.setBackground(Color.WHITE);

        g2d.setStroke(new BasicStroke(1.2f));

        Font font = g2d.getFont();

        //画出染色体名称
        //FontMetrics fontMetrics = g2d.getFontMetrics();
        int i = 1;
        for (Chromosome chr : chroms.getList()) {
            Font newFont = new Font("Arial", Font.BOLD, 30);
            g2d.setFont(newFont);
            //draw score line
            g2d.setColor(CytobandColor.color);
            g2d.setStroke(new BasicStroke(2.0f));
            g2d.drawLine((int) (x0 + chr.getStart() / scale), y0 + (i - 1) * (height + margin) - 10, (int) (x0 + chr.getLength() / scale), y0 + (i - 1) * (height + margin) - 10);

            g2d.setStroke(new BasicStroke(2.0f));
            g2d.setColor(CytobandColor.color);
            g2d.drawString(chr.getChrName(), 10, y0 + (i - 1) * (height + margin) + height);

            g2d.setFont(font);

            List<Cytoband> bands = chr.getBands();

            //begin to draw cytoband one by one
            for (Cytoband cytoband : bands) {
                g2d.setColor(CytobandColor.getColor(cytoband.getColor()));
                g2d.drawRect(x0 + (int) (cytoband.getStart() / scale), y0 + (i - 1) * (height + margin), (int) ((cytoband.getEnd() - cytoband.getStart()) / scale), height);
                g2d.fillRect(x0 + (int) (cytoband.getStart() / scale), y0 + (i - 1) * (height + margin), (int) ((cytoband.getEnd() - cytoband.getStart()) / scale), height);

                //是否显示cytoband名称
                if (drawText) {
                    int x = (int) (x0 + ((cytoband.getEnd()) / (scale)) - (cytoband.getEnd() - cytoband.getStart()) / (2 * scale));
                    if (x < cytoband.getEnd() / scale) {
                        x = (int) ((cytoband.getEnd()) / (scale) + 10);
                    }
                    int y = y0 + (i - 1) * (height + margin) + height + margin/2;
                    //System.out.println(x + "\t" + y);

                    g2d.rotate(-Math.PI / 2, x, y);
                    g2d.setColor(Color.BLACK);
                    newFont = new Font("Arial", Font.BOLD, 15);
                    g2d.setFont(newFont);
                    g2d.drawString(cytoband.getBandName(), x, y);
                    g2d.rotate(Math.PI / 2, x, y);
                }

                g2d.setColor(Color.WHITE);
                g2d.setFont(font);
            }//end draw cytoband

            //begin to draw mutations
            Logger.getLogger(MultipleCytobandViewer.class.getName()).log(Level.INFO, "there are {0} mutations found in chromosome  {1} .", new Object[]{chr.getMutations().size(), chr.getChrName()});
            for (Mutation mutation : chr.getMutations()) {
                int start = (int) mutation.getStart() / scale;
                int stop = (int) mutation.getEnd() / scale;

                int width = stop - start <= 1 ? 3 : stop - start;

                if (mutation.getType() == MutationType.SNP) {
                    g2d.setColor(CytobandColor.SNP);
                } else if (mutation.getType() == MutationType.INDEL) {
                    g2d.setColor(CytobandColor.INDEL);
                } else if (mutation.getType() == MutationType.CNV) {
                    g2d.setColor(CytobandColor.CNV);
                }
                g2d.setStroke(new BasicStroke(3.0F));

                g2d.fillRect(x0 + start, y0 + (i - 1) * (height + margin) - 2 * height, width, 10*2);
            }
            //reset color
            g2d.setColor(Color.WHITE);
            i++;
            //break;
        }

        g2d.dispose();
        return image;
    }

    /**
     * 保存图片
     *
     * @param image
     * @param filename
     * @param format
     */
    public void saveImage(BufferedImage image, String filename, String format) {

        try ( /*输出到文件流*/FileOutputStream newimage = new FileOutputStream(filename)) {
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);
            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(image);
            /* 压缩质量 */
            jep.setQuality(1f, true);
            encoder.encode(image, jep);
            /*近JPEG编码*/
        } catch (Exception e) {

        }

    }

    public static void main(String args[]) {

//        if (args.length < 2) {
//            System.out.println("usage:java -jar CytobandViewer.jar  <mutations file> <image file>");
//            System.exit(0);
//        }
        MultipleCytobandViewer util = new MultipleCytobandViewer();
         //util.saveImage(util.drawImage("D:\\染色体图\\染色体图2015-09-06\\EZ15071701HNHB.txt",true), "D:\\染色体图\\染色体图2015-09-06\\EZ15071701HNHB.jpg", "jpg");
        //drawMutation
        util.saveImage(util.drawMutation(new String[]{"D:\\染色体图\\染色体图2015-09-06\\EZ15071701HNHB.txt","D:\\染色体图\\染色体图2015-09-06\\EZ15071701HNHT.txt"},true), "D:\\染色体图\\染色体图2015-09-06\\EZ15071701HNHB.jpg", "jpg");
    }

    private Chromosomes initChromosomes(String mutationFile) {
        Chromosomes chroms = null;
        try {

            ChromosomeBuilder cBuilder = new ChromosomeBuilder().newBuilder().withCytoband(new File(DIR.replaceAll("\\\\", "/") + "/cytoband.txt"));
            
            if (mutationFile != null) {
                cBuilder.withMutations(new File(mutationFile));
            }

            chroms = cBuilder.builder();
        } catch (IOException ex) {
            Logger.getLogger(MultipleCytobandViewer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return chroms;
    }
}
